package com.yzc.service.Impl;


import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yzc.Authentication.JwtAuthenticationToken;
import com.yzc.apis.TourOrderClient;
import com.yzc.constants.MqConstants;
import com.yzc.execption.ZcException;
import com.yzc.mapper.TicketAttractionOrderMapper;
import com.yzc.mapper.TicketMainOrderMapper;
import com.yzc.model.DTO.AttractionOrderDetail;
import com.yzc.model.entity.ticket_order.OrderAttraction;
import com.yzc.model.entity.ticket_order.OrderMain;
import com.yzc.model.vo.page.PageResult;
import com.yzc.model.vo.ticket_order.AttractionOrderVO;
import com.yzc.model.vo.ticket_order.v_AttractionOrderVo;
import com.yzc.rabbit.OrderStatus;
import com.yzc.redis.RedisUtil;
import com.yzc.result.Result;
import com.yzc.result.ResultCodeEnum;
import com.yzc.service.TicketAttractionOrderService;
import com.yzc.snow.SnowflakeIdUtil;
import com.yzc.util.RabbitMQUtil;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Random;

import static com.yzc.constant.RedisConstant.*;
import static com.yzc.rabbit.OrderType.TRAVEL;

@Slf4j
@Service
@RequiredArgsConstructor
public class TicketAttractionOrderServiceImpl extends ServiceImpl<TicketAttractionOrderMapper, OrderAttraction>
        implements TicketAttractionOrderService {


    private final TicketAttractionOrderMapper mapper;
    private final TicketMainOrderMapper mainOrderMapper;
    private final SnowflakeIdUtil snowflakeIdUtil;
    private final PaymentServiceImpl paymentService;
    private final RabbitMQUtil rabbitMQUtil;
    private final TourOrderClient tourOrderClient;
    private final RedisUtil redisUtil;

    /**
     * 设置 SnowflakeIdUtil 的 machineId
     */
    private void setMachineId() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication instanceof JwtAuthenticationToken) {
            JwtAuthenticationToken jwtAuthentication = (JwtAuthenticationToken) authentication;
            snowflakeIdUtil.setMachineId(Long.parseLong(jwtAuthentication.getUserId()));
        } else {
            snowflakeIdUtil.setMachineId(1); // 默认值
        }
    }

    @Override
    public PageResult<AttractionOrderVO> listOrders(Long userId, Integer pageNo, Integer pageSize) {
        if (pageNo < 1 || pageSize < 1) {
            throw new IllegalArgumentException("分页参数必须大于0");
        }

        int offset = (pageNo - 1) * pageSize;

        try {
            // 执行查询
            List<AttractionOrderVO> orders = mainOrderMapper.findAttractionOrdersByUserId(userId, pageSize, offset);

            // 获取总记录数
            Long total = mainOrderMapper.countAttractionOrders(userId);

            // 封装分页结果
            PageResult<AttractionOrderVO> result = new PageResult<>();
            result.setPageNo(pageNo);
            result.setPageSize(pageSize);
            result.setTotal(total);
            result.setData(orders);

            log.info("查询订单列表成功，用户ID: {}", userId);
            return result;
        } catch (Exception e) {
            log.error("查询订单列表失败，用户ID: {}", userId, e);
            throw new RuntimeException("查询订单列表失败", e);
        }
    }

    @GlobalTransactional(name="zc-create-order",rollbackFor = Exception.class,timeoutMills = 30)
    @Override
    public void createTicketOrder(AttractionOrderDetail attraction) {
        setMachineId();
        long orderId = snowflakeIdUtil.nextId();

        try {
            log.info("开始创建订单，用户ID: {}, 景点ID: {}", attraction.getUserId(), attraction.getAttractionId());

            // 创建主订单和景点订单
            createOrderAndAttraction(orderId, attraction);

            // 扣减库存
            updateStock(attraction, orderId);

            // 发送延迟消息
            sendDelayedMessage(orderId);

            log.info("订单创建成功，订单ID: {}", orderId);
        } catch (Exception e) {
            log.error("订单创建或库存扣减失败，订单ID: {}", orderId, e);
            throw new ZcException(ResultCodeEnum.FAIL.getCode(), e.getMessage());
        }
    }

    private void createOrderAndAttraction(long orderId, AttractionOrderDetail attraction) {
        OrderMain mainOrder = new OrderMain();
        mainOrder.setOrderId(orderId);
        mainOrder.setUserId(attraction.getUserId());
        mainOrder.setOrderType(TRAVEL.getCode());
        mainOrder.setTotalAmount(attraction.getTotalAmount());
        mainOrder.setOrderStatus(OrderStatus.status_UNPAID.getCode());
        mainOrder.setCreateTime(new Date());
        mainOrderMapper.insert(mainOrder);
        log.info("主订单创建成功，订单内容: {}", mainOrder);

        mapper.createTicketOrder(attraction, orderId);
        log.info("景点订单创建成功，订单ID: {}", orderId);

        // 创建 v_AttractionOrderVo 对象并存储到缓存
        v_AttractionOrderVo attractionOrderVo = new v_AttractionOrderVo();
        attractionOrderVo.setOrderId(orderId);
        attractionOrderVo.setUserId(attraction.getUserId());
        attractionOrderVo.setOrderType(TRAVEL.getCode());
        attractionOrderVo.setTotalAmount(attraction.getTotalAmount());
        attractionOrderVo.setOrderStatus(OrderStatus.status_UNPAID.getCode());
        attractionOrderVo.setCreateTime(new Date());
        attractionOrderVo.setAttractionId(attraction.getAttractionId());
        attractionOrderVo.setVisitDate(attraction.getVisitDate());
        attractionOrderVo.setTicketType(attraction.getTicketType());
        attractionOrderVo.setTicketCount(attraction.getTicketCount());

        // 设置随机过期时间，避免缓存雪崩
        int expireTime = CACHE_EXPIRE_TIME + new Random().nextInt(CACHE_RANDOM_RANGE);
        redisUtil.set(ORDER_RECORD_MAIN + orderId, mainOrder, expireTime);
        redisUtil.set(ATTRACTION_ORDER_VO + orderId, attractionOrderVo, expireTime);
    }


    private void updateStock(AttractionOrderDetail attraction, long orderId) {
        tourOrderClient.updateStock(attraction.getAttractionId(), -attraction.getTicketCount(), orderId);
        log.info("库存扣减成功，景点ID: {}, 订单ID: {}", attraction.getAttractionId(), orderId);
    }

    @Async
    public void sendDelayedMessage(long orderId) {
        try {
            rabbitMQUtil.sendStaggeredDelayedMessages(
                    MqConstants.DELAY_EXCHANGE_NAME,
                    "order.unpaid",
                    orderId
            );
            log.info("延迟消息发送成功，订单ID: {}", orderId);
        } catch (Exception e) {
            log.error("延迟消息发送失败，订单ID: {}", orderId, e);
            throw new ZcException(ResultCodeEnum.FAIL.getCode(), "延迟消息发送失败");
        }
    }


    @Override
    @Transactional
    public Result<String> payOrder(Long orderId, String paymentMethod) {
        return paymentService.payOrder(orderId, paymentMethod);
    }
}